/**
 * @(#) Actuator.java
 */

package pcsr.hwVirtualization;

import java.util.*;

import pcsr.exceptions.PCSRActuatorRuntimeException;

/**
 * Represents a virtualized actuator, managed by PCSR.
 * @author Paulo Fagundes
 *
 */
public class Actuator implements IActuatorActions, IActuatorObservable
{
	private String actuatorID;
	
	private List<IActuatorObserver> actuatorObservers;
	
	private ActuatorMode actuatorOperationMode;

	private ActuatorValue actuatorValue;

	private IRobotDriver robot;
	
	/**
	 * Gets the identifier of the actuator.
	 * @return The actuatorID
	 */
	public String GetActuatorID( ) {
		try
		{
			return actuatorID;
		}
		catch (RuntimeException re) {
			throw new PCSRActuatorRuntimeException(re);
		}
	}
	
	/**
	 * {@inheritDoc}
	 */
	@Override
	public Actuator GetActuatorStatus( ) {
		try {
			return (Actuator)this.clone();
		} catch (Exception e) {
			throw new PCSRActuatorRuntimeException(e);
		}
	}
	/**
	 * Gets the actuator value.
	 * @return The actuatorValue
	 */
	public ActuatorValue GetActuatorValue( ) {
		try
		{
			return actuatorValue;
		}
		catch (RuntimeException re) {
			throw new PCSRActuatorRuntimeException(re);
		}
	}

	/**
	 * Gets the actuator operation mode.
	 * @return The actuatorOperationMode
	 */
	public ActuatorMode GetOperationMode( ) {
		try
		{
			return actuatorOperationMode;
		}
		catch (RuntimeException re) {
			throw new PCSRActuatorRuntimeException(re);
		}
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public void ObserveActuator( IActuatorObserver observer ) {
		try
		{
			actuatorObservers.add(observer);
		} catch (Exception e) {
			throw new PCSRActuatorRuntimeException(e);
		}
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public void SetActuatorMode( ActuatorMode actuatorMode ) {
		try
		{
			this.actuatorOperationMode = actuatorMode;
			robot.SetActuatorStatusToDriver(this);
		} catch (Exception e) {
			throw new PCSRActuatorRuntimeException(e);
		}
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public void SetActuatorValue( ActuatorValue actuatorValue ) {
		try
		{
			this.actuatorValue = actuatorValue;
			robot.SetActuatorStatusToDriver(this);
		} catch (Exception e) {
			throw new PCSRActuatorRuntimeException(e);
		}
	}

	/**
	 * Sets a new actuator mode.
	 * @param am The actuator mode to set.
	 */
	public void SetMode(ActuatorMode am) {
		try
		{
			this.actuatorOperationMode = am;
			NotifyObservers();
		}
		catch (RuntimeException re) {
			throw new PCSRActuatorRuntimeException(re);
		}
	}

	/**
	 * Sets a new operation mode.
	 * @param actuatorOperationMode The actuatorOperationMode to set
	 */
	public void SetOperationMode( ActuatorMode actuatorOperationMode ) {
		try
		{
			this.actuatorOperationMode = actuatorOperationMode;
			robot.SetActuatorStatusToDriver(this);
		}
		catch (RuntimeException re) {
			throw new PCSRActuatorRuntimeException(re);
		}
	}

	/**
	 * Sets the actuator value.
	 * @param actuatorValue the actuatorValue to set
	 */
	public void SetValue( ActuatorValue actuatorValue ) {
		try
		{
			this.actuatorValue = actuatorValue;
			NotifyObservers();
		}
		catch (RuntimeException re) {
			throw new PCSRActuatorRuntimeException(re);
		}
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public void UnObserveActuator( IActuatorObserver observer ) {
		try
		{
			actuatorObservers.remove(observer);
		} catch (Exception e) {
			throw new PCSRActuatorRuntimeException(e);
		}
	}

	/**
	 * Notify all subscribers that the actuator has changed.
	 */
	private void NotifyObservers()
	{
		for(IActuatorObserver ia : actuatorObservers)
		{
			ia.ActuatorChanged(this);
		}
	}

	/**
	 * Sets the {@code IRobotDriver} that connects to driver.
	 * @param robot The robot to set
	 */
	void setRobotDriver(IRobotDriver robot) {
		this.robot = robot;
	}
	
	{
		actuatorObservers = new LinkedList<IActuatorObserver>();
	}

	/**
	 * Actuator constructor.
	 * @param ID The actuator identifier
	 */
	public Actuator(String ID)
	{
		actuatorID = ID;
	}

	
}
